#include "usart.h"
#include "includes.h"
#include <string.h>
#include "esp8266.h"
#include "delay.h"
#include "sys.h"

#pragma import(__use_no_semihosting_swi)

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

volatile int8_t g_usart1_rx_buf[32]={0};  // 用于接收串口1的数据
volatile uint8_t g_usart1_rx_cnt=0;      // 串口1接收到的数据大小
volatile uint8_t g_usart1_rx_end=0;    // 用于串口1标明一条数据结束

int fputc(int ch, FILE *f) 
{
	USART_SendData(USART1,ch);
	//等待发送完毕
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);	
	//清空标志位
	USART_ClearFlag(USART1,USART_FLAG_TXE);
	//返回成功发送的字符
	return ch;
}


void _sys_exit(int return_code) 
{
	label: goto label; /* endless loop */
}


/**
 @brief 初始化串口1
 @param baud: 波特率,串口传输速度
*/
void usart1_init(uint32_t baud)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//打开硬件时钟：GPIO端口硬件时钟、USART硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//配置GPIO引脚为复用功能模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;	//指定9、10号引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//配置为复用功能模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//速度越高，功耗就越高，但是响应速度也更快
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不需要使能内部上下拉电阻
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	
	//将对应的GPIO引脚连接到串口
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);	
	
	//配置串口相关的参数：串口号，波特率，数据位，停止位，流控制
	USART_InitStructure.USART_BaudRate = baud;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);
	
	//配置串口相关的中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 6;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	//使能串口工作
	USART_Cmd(USART1, ENABLE);
}


/**
 @brief 初始化串口2,用于蓝牙
 @param baud: 波特率,串口传输速度
*/
void usart2_init(uint32_t baud)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//打开GPIOA/USART2的时钟，供电
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//端口PA2 PA3做为发送、接收
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      //复用功能
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  //不需要任何上拉
	GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//由于引脚支持很多功能，需要指定该引脚的功能，当前要制定支持USART2
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);		
	
	//初始化USART2
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制功能不需要
	USART_InitStructure.USART_BaudRate = baud;                      //设置波特率
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //运行发送、接收
	USART_InitStructure.USART_Parity = USART_Parity_No;             //不需要校验位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;          //一个停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;     //8个数据位
	USART_Init(USART2, &USART_InitStructure);

	//配置中断触发方式，接收到一个字节，就通知CPU处理
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;			//串口中断2号
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY;//中断抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;		//响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//打开通道给NVIC管理
	NVIC_Init(&NVIC_InitStructure);
	
	//使能USART2工作
	USART_Cmd(USART2, ENABLE);	
}




/**
 @brief 初始化串口3,用于蓝牙或wifi连接
 @param baud: 波特率,串口传输速度
*/
void usart3_init(uint32_t baud)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//使能端口B硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	
	//使能串口3硬件时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	
	//配置PB10、PB11为复用功能引脚
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10|GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;	
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	//将PB10、PB11连接到USART3的硬件
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
	
	
	//配置USART1的相关参数：波特率、数据位、校验位
	USART_InitStructure.USART_BaudRate = baud;//波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//允许串口发送和接收数据
	USART_Init(USART3, &USART_InitStructure);
	
	
	//使能串口接收到数据触发中断
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	//使能串口3工作
	USART_Cmd(USART3,ENABLE);
}


/**
 @brief 串口1中断处理函数,用于串口打印
*/
void USART1_IRQHandler(void)
{
	uint8_t d;
	
	/* USART in Receiver mode */
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		d = USART_ReceiveData(USART1);
		
		USART_SendData(USART1,d);
		
		g_usart1_rx_buf[g_usart1_rx_cnt++]=d;
		
		if(d == '#' || g_usart1_rx_cnt >= sizeof(g_usart1_rx_buf))
		{
			printf("\r\n");
			g_usart1_rx_end=1;
		}
		
#if EN_DEBUG_ESP8266		
		//将接收到的数据发给串口3
		USART_SendData(USART3,d);
		while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
#endif
	  
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
}


void USART2_IRQHandler(void)
{
	uint32_t ulReturn;
	BaseType_t  xHigherPriorityTaskWoken = pdFALSE;
	static struct usart2_packet g_usart2_packet={0};
	
	/* 进入临界段，临界段可以被更高抢占优先级的中断嵌套 */
	ulReturn = taskENTER_CRITICAL_FROM_ISR();	
	
	if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
	{
		g_usart2_packet.recv_buf[g_usart2_packet.recv_cnt++] = USART_ReceiveData(USART2); //返回一个字节
		
		//结束符'\n',发送消息队列到usart任务
		if(g_usart2_packet.recv_buf[g_usart2_packet.recv_cnt-1] == '\n' || g_usart2_packet.recv_cnt>= sizeof g_usart2_packet.recv_buf)
		{
			xQueueSendFromISR(g_queue_usart2,(void *)&g_usart2_packet,&xHigherPriorityTaskWoken);
			
			memset(&g_usart2_packet,0,sizeof g_usart2_packet); //清零
		}
		
		/* 告诉CPU，已经完成接收中断请求，可以响应新的接收中断请求 */
		USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除标志位	
	}	
	
	/* 退出临界段 */
	taskEXIT_CRITICAL_FROM_ISR(ulReturn);	
}


/**
 @brief 串口3中断处理函数,用于从串口3获取数据
*/
void USART3_IRQHandler(void)
{
	uint8_t d=0;
	
	uint32_t ulReturn;
	
	/* 进入临界段，临界段可以被更高抢占优先级的中断嵌套 */
	ulReturn = taskENTER_CRITICAL_FROM_ISR();	
	
	//检测是否接收到数据
	if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
	{
		d=USART_ReceiveData(USART3);
		
		g_esp8266_rx_buf[g_esp8266_rx_cnt++]=d;
		
		if(g_esp8266_rx_cnt >= sizeof g_esp8266_rx_buf)
		{
			g_esp8266_rx_end=1;
		}

#if EN_DEBUG_ESP8266			
		//将接收到的数据返发给PC
		USART_SendData(USART1,d);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
#endif
		
		//清空标志位，可以响应新的中断请求
		USART_ClearITPendingBit(USART3, USART_IT_RXNE);
	}
	
	/* 退出临界段 */
	taskEXIT_CRITICAL_FROM_ISR(ulReturn);

}


/**
 @brief 向串口2发送字符串
 @param str: 字符串
*/
void usart2_send_str(char *str)
{
	char *p = str;
	
	while(*p!='\0')
	{
		USART_SendData(USART2,*p);
		
		p++;
		
		//等待数据发送成功
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
		USART_ClearFlag(USART2,USART_FLAG_TXE);
	}
}


/**
 @brief 向串口3发送字符串
 @param str: 字符串
*/
void usart3_send_str(char *str)
{
	char *p = str;
	//等待互斥锁
	xSemaphoreTake(xMutex, portMAX_DELAY);
	while(*p!='\0')
	{
		USART_SendData(USART3,*p);
		p++;
		
		//等待数据发送成功
		while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
	}
	//立即释放互斥锁
	xSemaphoreGive(xMutex);
}


/**
 @brief 向串口3发送字节数组
 @param buf: 字节数组
 @param len: 数组长度
*/
void usart3_send_bytes(uint8_t *buf,uint32_t len)
{
	uint8_t *p = buf;
	
	while(len--)
	{
		USART_SendData(USART3,*p);
		p++;
		
		//等待数据发送成功
		while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
	}
}






void usart3_test(void)
{
	//usart3初始化
	usart3_init(115200);

	//设置为SoftAP+Station 模式	
	usart3_send_str("AT+CWMODE=2\r\n"); 
	delay_ms(2000);	
	
	//创建热点
	usart3_send_str("AT+CWSAP=\"tkzc\",\"88888888\",1,4\r\n");
	delay_ms(2000);
	
	/* 设置多客户端连接模式 */
	usart3_send_str("AT+CIPMUX=1\r\n");
	delay_ms(2000);
	
	/* 建立TCP服务器，端口号为8080 */
	usart3_send_str("AT+CIPSERVER=1,8080\r\n");
	
	delay_ms(2000);
	printf("esp82266 wifi init finish\r\n");
}
